from socket import *
from threading import Thread
import os
from time import sleep

FTP = "d:/FTP/"

class Handle:
    def __init__(self,connfd):
        self.connfd = connfd

    def show_list(self):
        filelist = os.listdir(FTP)
        if filelist:
            self.connfd.send(b'OK')
            sleep(0.1)
            files = "\n".join(filelist)
            self.connfd.send(files.encode())
        else:
            self.connfd.send(b'No Files')
    def get_file(self, filename):
        try:
            file = open(FTP+filename,"rb")
        except:
            self.connfd.send(b'No File')
        else:
            self.connfd.send(b"OK")
            sleep(0.1)
            while True:
                data = file.read(1024)
                if not data:
                    break
                self.connfd.send(data)
            file.close()
            sleep(0.1)
            self.connfd.send(b"##")
    def put_file(self, filename):
        if os.path.exists(FTP+filename):
            self.connfd.send(b"ERROR! File Exists!")
        else:
            self.connfd.send(b"OK")
            file = open(FTP+filename, 'wb')
            while True:
                data = self.connfd.recv(1024)
                if data == b"##":
                    break
                file.write(data)
            file.close()
    def request(self):
        while True:
            data = self.connfd.recv(1024).decode()
            tmp = data.split(' ')
            if not data or tmp[0] == 'EXIT':
                break
            elif tmp[0] == 'LIST':
                self.show_list()
            elif tmp[0] == 'GET':
                self.get_file(tmp[1])
            elif tmp[0] == 'PUT':
                self.put_file()

class FTPThread(Thread):
    def __init__(self, connfd):
        self.connfd = connfd
        self.handle = Handle(connfd)
        super().__init__(daemon=True)

    def run(self):
        self.handle.request()
        self.connfd.close()

class ConcurrentServer:
    def __init__(self, * , host="", port=0):
        self.host = host
        self.port = port
        self.address = (host, port)
        self.sock = self.__create_socket()

    def __create_socket(self):
        tcp_socket = socket()
        tcp_socket.bind(self.address)
        return tcp_socket

    def serve_forever(self):
        self.sock.listen(5)
        print(f"Listen the port {self.port}")

        while True:
            connfd, addr = self.sock.accept()
            print("Connect from :",addr)
            t = FTPThread(connfd)
            t.start()

if __name__=='__main__':
    server = ConcurrentServer(host='0.0.0.0', port=8880)
    server.serve_forever()